package org.spring.context.support;

import org.spring.beans.BeanDefination;
import org.spring.beans.factory.NoSuchBeanDefinationException;
import org.spring.beans.factory.annotation.AutowiredAnnotationProcessor;
import org.spring.beans.factory.config.ConfigurableBeanFactory;
import org.spring.beans.factory.support.DefaultBeanFactory;
import org.spring.beans.factory.xml.XMLBeanDefinationReader;
import org.spring.context.ApplicationContext;
import org.spring.core.io.Resource;
import org.spring.util.ClassUtils;

public abstract class AbstractApplicationContext implements ApplicationContext {
	private DefaultBeanFactory factory;
	private ClassLoader classLoader;

	public AbstractApplicationContext(String configFile) {
		factory = new DefaultBeanFactory();
		XMLBeanDefinationReader reader = new XMLBeanDefinationReader(factory);
		reader.loadBeanDefination(getResourceByPath(configFile));
		factory.setClassLoader(this.getClassLoader());
		registerBeanPostProcessors(factory);
	}

	public BeanDefination getBeanDefination(String beanID) {
		return factory.getBeanDefination(beanID);
	}

	public Object getBean(String beanId) {
		return factory.getBean(beanId);
	}

	protected abstract Resource getResourceByPath(String path);

	public void setClassLoader(ClassLoader classLoader) {
		this.classLoader = classLoader;
	}

	public ClassLoader getClassLoader() {
		return this.classLoader != null ? this.classLoader : ClassUtils.getDefaultClassLoader();
	}

	protected void registerBeanPostProcessors(ConfigurableBeanFactory beanFactory) {
		AutowiredAnnotationProcessor postProcessor = new AutowiredAnnotationProcessor();
		postProcessor.setBeanFactory(beanFactory);
		beanFactory.addBeanPostProcessor(postProcessor);
	}
	
	public Class<?> getType(String targetBeanName) throws NoSuchBeanDefinationException {
		return this.factory.getType(targetBeanName);
	}
}
